import { computed, defineComponent, ref, watchEffect } from 'vue'
import './menu.less'

function IconAngle() {
  return (
    <svg
      aria-hidden="true"
      focusable="false"
      role="img"
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 35 35">
      <path
        fill="currentColor"
        d="M9.4,13.9c-0.2,0.2-0.2,0.6,0,0.8l8.1,8.1l0,0l0,0l8.1-8.1c0.2-0.2,0.2-0.6,0-0.8l-1.3-1.3 c-0.2-0.2-0.6-0.2-0.8,0l-5.5,5.5c-0.2,0.2-0.6,0.2-0.8,0l-5.5-5.5c-0.2-0.2-0.6-0.2-0.8,0L9.4,13.9z">
      </path>
    </svg>
  )
}

function IconFolder() {
  return (
    <svg
      aria-hidden="true"
      focusable="false"
      role="img"
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 512 512">
      <path
        fill="currentColor"
        d="M464 128H272l-64-64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V176c0-26.51-21.49-48-48-48z">
      </path>
    </svg>
  )
}

// eslint-disable-next-line vue/one-component-per-file
const MenuItem = defineComponent({
  name: 'MenuItem',
  props: {
    data: {
      type: Object,
      required: true
    },
    checkedIds: {
      type: Array,
      default () {
        return []
      }
    },
    expandIds: {
      type: Array,
      default () {
        return []
      }
    },
    itemWrap: {
      type: Function,
      default: undefined
    },
    itemRender: {
      type: Function,
      default: undefined
    },
    itemCtrl: {
      type: Function,
      default: undefined
    },
    onChecked: {
      type: Function,
      default: undefined
    },
    onCollapsed: {
      type: Function,
      default: undefined
    }
  },
  setup(props) {
    // eslint-disable-next-line vue/no-setup-props-destructure
    const item = props.data
    const hasChildren = !!item.children
    const collapsed = ref(!(item.id && props.expandIds.indexOf(item.id) > -1))
    const hovered = ref(false)

    const checked = computed(() => item.id && props.checkedIds.indexOf(item.id) > -1)

    watchEffect(() => {
      if (item.id) {
        collapsed.value = !(props.expandIds.indexOf(item.id) > -1)
      }
    })

    const onItemClick = () => {
      if (hasChildren) {
        collapsed.value = !collapsed.value
        props.onCollapsed && props.onCollapsed(item, collapsed.value)
      }

      (props.onChecked && item.id) && props.onChecked(item)
    }

    const onRowMouseEnter = () => {
      hovered.value = true
    }

    const onRowMouseLeave = () => {
      hovered.value = false
    }

    return () => item.hide ? null : (
      <li class={['menu-item', {
        'is-open': hasChildren && !collapsed.value,
        'is-group': item.isGroup
      }]}>
        {item.isGroup ? (
          <div class="menu-group-title">{item.label}</div>
        ) : props.itemWrap(item, <div className="menu-item-wrap"
          onClick={onItemClick}
          onMouseenter={onRowMouseEnter}
          onMouseleave={onRowMouseLeave}
        >
          <div class={['menu-item--row', {
            'is-checked': checked.value,
            'is-hovered': hovered.value,
            'has-children': hasChildren
          }]}></div>
          <div className="menu-item--content">
            <div className="menu-item--ocl">
              <span className="menu-item--icon collapse-icon">{hasChildren ? <IconAngle></IconAngle> : null}</span>
            </div>
            <div className="menu-item--label">
              {props.itemRender ? props.itemRender(item) : (hasChildren
                ? (
                  <>
                    <span className="menu-item--icon folder-icon">
                      <IconFolder />
                    </span>
                    <span className="menu-item--text">{item.label}</span>
                  </>
                )
                : (
                  <>
                    <span className="menu-item--icon folder-icon">
                      {item.icon}
                    </span>
                    <span className="menu-item--text">{item.label}</span>
                  </>
                ))}
            </div>
            {props.itemCtrl ? <div className="menu-item--ctrl">{props.itemCtrl(item)}</div> : null}
          </div>
        </div>)}
        {item.children ? (
          <Menu
            data={item.children}
            isChild={true}
            checkedIds={props.checkedIds}
            expandIds={props.expandIds}
            itemWrap={props.itemWrap}
            itemRender={props.itemRender}
            itemCtrl={props.itemCtrl}
            onChecked={props.onChecked}
            onCollapsed={props.onCollapsed}
          />
        ) : null}
      </li>
    )
  }
})

// eslint-disable-next-line vue/one-component-per-file
const Menu = defineComponent({
  name: 'Menu',
  props: {
    data: {
      type: Array,
      default() {
        return []
      }
    },
    checkedIds: {
      type: Array,
      default() {
        return []
      }
    },
    expandIds: {
      type: Array,
      default() {
        return []
      }
    },
    isChild: Boolean,
    itemWrap: {
      type: Function,
      default(item, c) {
        return c
      }
    },
    itemRender: {
      type: Function,
      default: undefined
    },
    itemCtrl: {
      type: Function,
      default: undefined
    },
    onChecked: {
      type: Function,
      default: undefined
    },
    onCollapsed: {
      type: Function,
      default: undefined
    }
  },
  emits: [],
  setup(props) {
    // eslint-disable-next-line vue/no-setup-props-destructure
    const menus = props.data
    return () => (
      <ul class={['menu', { 'is-child': props.isChild }]}>
        {menus.map((e, index) => {
          return (
            <MenuItem
              key={index}
              data={e}
              checkedIds={props.checkedIds}
              expandIds={props.expandIds}
              itemWrap={props.itemWrap}
              itemRender={props.itemRender}
              itemCtrl={props.itemCtrl}
              onChecked={props.onChecked}
              onCollapsed={props.onCollapsed} />
          )
        })}
      </ul>
    )
  }
})

export default Menu
